﻿using ImoviesBlazor.Server.Helpers;
using ImoviesBlazor.Server.Repository;
using ImoviesBlazor.Shared;
using ImoviesBlazor.Shared.Entities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace ImoviesBlazor.Server.Controllers
{
    /// <summary>
    /// 视频采集控制器
    /// </summary>
    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class CollectController : ControllerBase
    {
        private readonly ITeleplayRepository _teleplayRepository;
        private readonly IMovieRepository _movieRepository;
        private readonly IAnimationRepository _animationRepository;
        private readonly ITeleplayVlinkRepository _teleplayVlinkRepository;
        private readonly IMovieVlinkRepository _movieVlinkRepository;
        private readonly IAnimationVlinkRepository _animationVlinkRepository;

        public CollectController(ITeleplayRepository teleplayRepository,
            IMovieRepository movieRepository,
            IAnimationRepository animationRepository,
            ITeleplayVlinkRepository teleplayVlinkRepository,
            IMovieVlinkRepository movieVlinkRepository,
            IAnimationVlinkRepository animationVlinkRepository)
        {
            this._teleplayRepository = teleplayRepository;
            this._movieRepository = movieRepository;
            this._animationRepository = animationRepository;
            this._teleplayVlinkRepository = teleplayVlinkRepository;
            this._movieVlinkRepository = movieVlinkRepository;
            this._animationVlinkRepository = animationVlinkRepository;
        }

        /// <summary>
        /// 电视剧采集
        /// </summary>
        /// <param name="urls">url列表</param>
        /// <returns></returns>
        [HttpPost("teleplay")]
        public async Task<ActionResult> TeleplayCollect([FromBody] List<string> urls)
        {
            foreach (string url in urls)
            {
                string html = await HtmlUtils.GetHtmlTxt(url);
                if (html == null)
                {
                    return Ok();
                }
                try
                {
                    var video = doCollect(html);
                    var videoInfo = video.Item1;
                    videoInfo.Url = url;
                    _teleplayRepository.AddTeleplay(new Teleplay(videoInfo.Id, videoInfo.Name,
                                                videoInfo.Url, videoInfo.Category,
                                                videoInfo.Region, videoInfo.Year,
                                                videoInfo.Actors, videoInfo.Director,
                                                videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

                    var links = video.Item2;
                    var vlinks = links.Select(x => new TeleplayVlink(videoInfo.Id, x.Key, x.Value));
                    await _teleplayVlinkRepository.BatchAddTeleplayVlink(vlinks);

                    await _teleplayRepository.SaveAsync();
                    await _teleplayVlinkRepository.SaveAsync();
                }
                catch
                {
                    continue;
                }

                await Task.Delay(100);
            }
            return Ok();
        }

        /// <summary>
        /// 电影采集
        /// </summary>
        /// <param name="urls">url列表</param>
        /// <returns></returns>
        [HttpPost("movie")]
        public async Task<ActionResult> MovieCollect([FromBody] List<string> urls)
        {
            foreach (string url in urls)
            {
                string html = await HtmlUtils.GetHtmlTxt(url);
                if (html == null)
                {
                    return Ok();
                }
                try
                {
                    var video = doCollect(html);
                    var videoInfo = video.Item1;
                    videoInfo.Url = url;
                    _movieRepository.AddMovie(new Movie(videoInfo.Id, videoInfo.Name,
                                                videoInfo.Url, videoInfo.Category,
                                                videoInfo.Region, videoInfo.Year,
                                                videoInfo.Actors, videoInfo.Director,
                                                videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

                    var links = video.Item2;
                    var vlinks = links.Select(x => new MovieVlink(videoInfo.Id, x.Key, x.Value));
                    await _movieVlinkRepository.BatchAddMovieVlink(vlinks);

                    await _movieRepository.SaveAsync();
                    await _movieVlinkRepository.SaveAsync();
                }
                catch
                {
                    continue;
                }

                await Task.Delay(100);
            }
            return Ok();
        }


        /// <summary>
        /// 动漫采集
        /// </summary>
        /// <param name="urls">url列表</param>
        /// <returns></returns>
        [HttpPost("animation")]
        public async Task<ActionResult> AnimationCollect([FromBody] List<string> urls)
        {
            foreach (string url in urls)
            {
                string html = await HtmlUtils.GetHtmlTxt(url);
                if (html == null)
                {
                    return Ok();
                }
                try
                {
                    var video = doCollect(html);
                    var videoInfo = video.Item1;
                    videoInfo.Url = url;
                    _animationRepository.AddAnimation(new Animation(videoInfo.Id, videoInfo.Name,
                                                videoInfo.Url, videoInfo.Category,
                                                videoInfo.Region, videoInfo.Year,
                                                videoInfo.Actors, videoInfo.Director,
                                                videoInfo.Intro, videoInfo.Img, videoInfo.Comment));

                    var links = video.Item2;
                    var vlinks = links.Select(x => new AnimationVlink(videoInfo.Id, x.Key, x.Value));
                    await _animationVlinkRepository.BatchAddMovieVlink(vlinks);

                    await _animationRepository.SaveAsync();
                    await _animationVlinkRepository.SaveAsync();
                }
                catch
                {
                    continue;
                }

                await Task.Delay(100);
            }
            return Ok();
        }


        /// <summary>
        /// html解析采集函数
        /// </summary>
        /// <param name="html">html文本</param>
        /// <returns>Tuple<VideoInfo, Dictionary<string, string>></returns>
        private Tuple<VideoInfo, Dictionary<string, string>> doCollect(string html)
        {
            VideoInfo info = new VideoInfo();

            string imgPattern = @"<img class=""lazyload"" data-original=""(.*?)"" src="".*"" />";
            Match imgMatch = Regex.Match(html, imgPattern);
            if (imgMatch.Success)
            {
                string img = imgMatch.Groups[1].Value;
                if (!img.StartsWith("http"))
                {
                    img = $"https://www.smdyy.cc{img}";
                }
                info.Img = img;
            }

            string titlePattern = @"<h1 class=""title"">(.*?)</h1>";
            Match titleMatch = Regex.Match(html, titlePattern);
            if (titleMatch.Success)
            {
                string title = titleMatch.Groups[1].Value;
                info.Name = title;
                // id赋值
                byte[] bytes = MD5.HashData(Encoding.UTF8.GetBytes(title));
                info.Id = BitConverter.ToString(bytes).Replace("-", "");
            }

            string cryPattern = @"<p class=""data"">类型：(.*?) / 地区：(.*?) / 年份：(.*?) /上映：.*</p>";
            Match cryMatch = Regex.Match(html, cryPattern);
            if (cryMatch.Success)
            {
                string cate = cryMatch.Groups[1].Value;
                string region = cryMatch.Groups[2].Value;
                uint year = uint.Parse(cryMatch.Groups[3].Value);
                info.Category = cate;
                info.Region = region;
                info.Year = year;
            }

            string actorsPattern = @"<p class=""data"">主演：(.*?)</p>";
            Match actorsMatch = Regex.Match(html, actorsPattern);
            if (actorsMatch.Success)
            {
                string actors = actorsMatch.Groups[1].Value;
                info.Actors = actors;
            }

            string directorPattern = @"<p class=""data"">导演：(.*?)</p>";
            Match directorMatch = Regex.Match(html, directorPattern);
            if (directorMatch.Success)
            {
                string director = directorMatch.Groups[1].Value;
                info.Director = director;
            }

            string introPattern = @"<span class=""detail-content"" style=""display: none;"">(.*?)</span>";
            Match introMatch = Regex.Match(html, introPattern);
            if (introMatch.Success)
            {
                string intro = introMatch.Groups[1].Value;
                info.Intro = intro;
            }


            Dictionary<string, string> links = new Dictionary<string, string>();
            string linksHtmlPattern = @"<ul class=""stui-content__playlist clearfix"">([\s\S]*?)</ul>";
            string linksPattern = @"<li ><a href=""(.*?)"">(.*?)</a></li>";
            Match linkHtml = Regex.Match(html, linksHtmlPattern);
            if (linkHtml.Success)
            {
                MatchCollection matchs = Regex.Matches(linkHtml.Value, linksPattern);
                if (matchs.Count > 0)
                {
                    foreach (Match m in matchs)
                    {
                        string linkUrl = $"https://www.smdyy.cc{m.Groups[1].Value}";
                        string linkTitle = m.Groups[2].Value;
                        links.Add(linkTitle, linkUrl);
                    }

                }
            }

            return Tuple.Create(info, links);
        }

    }
}
